home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Add-On
/
Workbench Add-On - Volume 1.iso
/
Music
/
EDIT
/
AmiSOX3.3
/
dist
/
8svx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-08-23
|
8KB
|
328 lines
/*
* Amiga 8SVX format handler: W V Neisius, February 1992
*/
#if defined(unix) || defined(__OS2__)
#include <sys/types.h>
#endif
#include <math.h>
#include <errno.h>
#ifdef VMS
#include <perror.h>
#endif
#include "st.h"
/* Private data used by writer */
struct svxpriv {
unsigned long nsamples;
FILE *ch[4];
};
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
/*======================================================================*/
/* 8SVXSTARTREAD */
/*======================================================================*/
svxstartread(ft)
ft_t ft;
{
struct svxpriv *p = (struct svxpriv *) ft->priv;
char buf[12];
char *endptr;
char *chunk_buf;
unsigned long totalsize;
unsigned long chunksize;
int channels;
long rate;
int littlendian = 0;
int i;
unsigned long chan1_pos;
rate = 0;
channels = 1;
/* read FORM chunk */
if (fread(buf, 1, 4, ft->fp) != 4 || strncmp(buf, "FORM", 4) != 0)
fail("8SVX: header does not begin with magic word 'FORM'");
totalsize = rblong(ft);
if (fread(buf, 1, 4, ft->fp) != 4 || strncmp(buf, "8SVX", 4) != 0)
fail("8SVX: 'FORM' chunk does not specify '8SVX' as type");
/* read chunks until 'BODY' (or end) */
while (fread(buf,1,4,ft->fp) == 4 && strncmp(buf,"BODY",4) != 0) {
if (strncmp(buf,"VHDR",4) == 0) {
chunksize = rblong(ft);
if (chunksize != 20)
fail ("8SVX: VHDR chunk has bad size");
fseek(ft->fp,12,SEEK_CUR);
rate = rbshort(ft);
fseek(ft->fp,1,SEEK_CUR);
fread(buf,1,1,ft->fp);
if (buf[0] != 0)
fail ("8SVX: unsupported data compression");
fseek(ft->fp,4,SEEK_CUR);
continue;
}
if (strncmp(buf,"ANNO",4) == 0) {
chunksize = rblong(ft);
if (chunksize & 1)
chunksize++;
chunk_buf = (char *) malloc(chunksize + 1);
if (fread(chunk_buf,1,(size_t)chunksize,ft->fp)
!= chunksize)
fail("8SVX: Unexpected EOF in ANNO header");
chunk_buf[chunksize] = '\0';
report ("%s",chunk_buf);
free(chunk_buf);
continue;
}
if (strncmp(buf,"NAME",4) == 0) {
chunksize = rblong(ft);
if (chunksize & 1)
chunksize++;
chunk_buf = (char *) malloc(chunksize + 1);
if (fread (chunk_buf,1,(size_t)chunksize,ft->fp)
!= chunksize)
fail("8SVX: Unexpected EOF in NAME header");
chunk_buf[chunksize] = '\0';
report ("%s",chunk_buf);
free(chunk_buf);
continue;
}
if (strncmp(buf,"CHAN",4) == 0) {
chunksize = rblong(ft);
if (chunksize != 4)
fail("8SVX: Short channel chunk");
channels = rblong(ft);
channels = (channels & 0x01) +
((channels & 0x02) >> 1) +
((channels & 0x04) >> 2) +
((channels & 0x08) >> 3);
continue;
}
/* some other kind of chunk */
chunksize = rblong(ft);
if (chunksize & 1)
chunksize++;
fseek(ft->fp,chunksize,SEEK_CUR);
continue;
}
if (rate == 0)
fail ("8SVX: invalid rate");
if (strncmp(buf,"BODY",4) != 0)
fail ("8SVX: BODY chunk not found");
p->nsamples = rblong(ft);
ft->info.channels = channels;
ft->info.rate = rate;
ft->info.style = SIGN2;
ft->info.size = BYTE;
/* open files to channels */
p->ch[0] = ft->fp;
chan1_pos = ftell(p->ch[0]);
for (i = 1; i < channels; i++) {
if ((p->ch[i] = fopen(ft->filename, READBINARY)) == NULL)
fail("Can't open channel file '%s': %s",
ft->filename, strerror(errno));
/* position channel files */
if (fseek(p->ch[i],chan1_pos,SEEK_SET))
fail ("Can't position channel %d: %s",i,strerror(errno));
if (fseek(p->ch[i],p->nsamples/channels*i,SEEK_CUR))
fail ("Can't seek channel %d: %s",i,strerror(errno));
}
endptr = (char *) &littlendian;
*endptr = 1;
if (littlendian == 1)
ft->swap = 1;
}
/*======================================================================*/
/* 8SVXREAD */
/*======================================================================*/
svxread(ft, buf, nsamp)
ft_t ft;
long *buf, nsamp;
{
register unsigned long datum;
int done = 0;
int i;
struct svxpriv *p = (struct svxpriv *) ft->priv;
while (done < nsamp) {
for (i = 0; i < ft->info.channels; i++) {
datum = getc(p->ch[i]);
if (feof(p->ch[i]))
return done;
/* scale signed up to long's range */
*buf++ = LEFT(datum, 24);
}
done += ft->info.channels;
}
return done;
}
/*======================================================================*/
/* 8SVXSTOPREAD */
/*======================================================================*/
svxstopread(ft)
ft_t ft;
{
int i;
struct svxpriv *p = (struct svxpriv *) ft->priv;
/* close channel files */
for (i = 1; i < ft->info.channels; i++) {
fclose (p->ch[i]);
}
}
/*======================================================================*/
/* 8SVXSTARTWRITE */
/*======================================================================*/
svxstartwrite(ft)
ft_t ft;
{
struct svxpriv *p = (struct svxpriv *) ft->priv;
int littlendian = 0;
int i;
char *endptr;
/* open channel output files */
p->ch[0] = ft->fp;
for (i = 1; i < ft->info.channels; i++) {
if ((p->ch[i] = tmpfile()) == NULL)
fail("Can't open channel output file: %s",
strerror(errno));
}
/* write header (channel 0) */
ft->info.style = SIGN2;
ft->info.size = BYTE;
p->nsamples = 0;
svxwriteheader(ft, p->nsamples);
endptr = (char *) &littlendian;
*endptr = 1;
if (littlendian == 1)
ft->swap = 1;
}
/*======================================================================*/
/* 8SVXWRITE */
/*======================================================================*/
svxwrite(ft, buf, len)
ft_t ft;
long *buf, len;
{
struct svxpriv *p = (struct svxpriv *) ft->priv;
register long datum;
int done = 0;
int i;
p->nsamples += len;
while(done < len) {
for (i = 0; i < ft->info.channels; i++) {
datum = RIGHT(*buf++, 24);
putc((int)datum, p->ch[i]);
}
done += ft->info.channels;
}
}
/*======================================================================*/
/* 8SVXSTOPWRITE */
/*======================================================================*/
svxstopwrite(ft)
ft_t ft;
{
struct svxpriv *p = (struct svxpriv *) ft->priv;
int i;
int len;
char svxbuf[512];
/* append all channel pieces to channel 0 */
/* close temp files */
for (i = 1; i < ft->info.channels; i++) {
if (fseek (p->ch[i], 0L, 0))
fail ("Can't rewind channel output file %d",i);
while (!feof(p->ch[i])) {
len = fread (svxbuf, 1, 512, p->ch[i]);
fwrite (svxbuf, 1, len, p->ch[0]);
}
fclose (p->ch[i]);
}
/* fixup file sizes in header */
if (fseek(ft->fp, 0L, 0) != 0)
fail("can't rewind output file to rewrite 8SVX header");
svxwriteheader(ft, p->nsamples);
}
/*======================================================================*/
/* 8SVXWRITEHEADER */
/*======================================================================*/
#define SVXHEADERSIZE 100
svxwriteheader(ft,nsamples)
ft_t ft;
long nsamples;
{
fputs ("FORM", ft->fp);
wblong(ft, nsamples + SVXHEADERSIZE - 8); /* size of file */
fputs("8SVX", ft->fp); /* File type */
fputs ("VHDR", ft->fp);
wblong(ft, (long) 20); /* number of bytes to follow */
wblong(ft, nsamples); /* samples, 1-shot */
wblong(ft, (long) 0); /* samples, repeat */
wblong(ft, (long) 0); /* samples per repeat cycle */
wbshort(ft, (int) ft->info.rate); /* samples per second */
fputc(1,ft->fp); /* number of octaves */
fputc(0,ft->fp); /* data compression (none) */
wbshort(ft,1); wbshort(ft,0); /* volume */
fputs ("ANNO", ft->fp);
wblong(ft, (long) 32); /* length of block */
fputs ("File created by Sound Exchange ", ft->fp);
fputs ("CHAN", ft->fp);
wblong(ft, (long) 4);
wblong(ft, (ft->info.channels == 2) ? (long) 6 :
(ft->info.channels == 4) ? (long) 15 : (long) 2);
fputs ("BODY", ft->fp);
wblong(ft, nsamples); /* samples in file */
}